<?php
class Silk_Objects extends Silk_Gateway
{

    protected $_dao_class   = 'Silk_Dao_Object';

    protected $_model_class = 'Silk_Object';

    protected $_primary_key = 'object_id';

    public function getMetaCollection($pObject, $pMeta){
	$Metas = new Silk_Metas();
	$metas = $Metas->getModelCollection($pMeta);

	return $metas;
    }

    public function fetchByType($pType, $pSiteId=null){
	if ($pSiteId){
	    $criteria = array('site_id' => $pSiteId, 'type' => $pType);
	} else
	    $criteria = array('type' => $pType);

	return $this->fetch($criteria);
    }

    public function fetchByRoute($pRoute, $pSiteId=null){

	logdebug("Silk_Objects.fetchByRoute: Searching for route [$pRoute] on site [$pSiteId]");

	$Routes = new Silk_Routes();

	if ($pSiteId){
	    $results = $Routes->fetch(array('route' => $pRoute, 'site_id' => $pSiteId));
	    if (count($results) > 0)
		$route = $results->current();
	    else
		$route = null;
	} else
	    $route  = $Routes->fetchByRoute($pRoute, true);

	if ($route){
	    return $route->getObject();
	} else {
	    $object = $this->fetchBySlug($pRoute, true);
	    return ($object) ? $object : null;
	}
    }

    public function render($pObject, $pAction=null, array $pVars=array()){
	$object = $this->getModelObject($pObject);
	$type   = $this->getType($object);

	return $type->render($pObject, $pAction, $pVars);
    }

    public function hasPermission($pObject, $pPrivilege, $pUser=null){
	$object_id = $this->getModelObjectId($pObject);
	$resource  = "object.{$object_id}";
	return Silk::HasPermission(array(
	    'resource' => $resource,
	    'privilege' => $pPrivilege,
	    $pUser
	));
    }

    public function getPermissions($pObject){
	$object = $this->getModelObject($pObject);
	if ($object->object_id)
	    $resource = "object.{$object->object_id}";
	else
	    $resource = "type.{$object->type_id}";

	$Permissions = new Silk_Permissions();
	return $Permissions->fetchByResource($resource);
    }

//     public function getPermissionsForRole($pObject, $pRole){
// 	$object_id = $this->getModelObjectId($pObject);
// 	$resource = "object.{$object_id}";
// 	$Permissions = new Silk_Permissions();
//
//     }

    public function clearPermissionsForUser($pObject, $pUser){
	$object_id = $this->getModelObjectId($pObject);
	$resource = "object.{$object_id}";

	$Users = new Silk_Users();
	$user_id = $Users->getModelObjectId($pUser);

	$Permissions = new Silk_Permissions();
	$permissions = $Permissions->fetchByResource($resource);

	foreach ($permissions as $permission){
	    Doctrine_Query::create()
		->delete('Silk_Dao_UserPermission up')
		->where('up.user_id = ?', $user_id)
		->andWhere('up.permission_id = ?', $permission->permission_id)
		->execute();
	}
    }

    public function clearPermissionsForRole($pObject, $pRole){
	$object_id = $this->getModelObjectId($pObject);
	$resource = "object.{$object_id}";

	$Roles = new Silk_Roles();
	$role_id = $Roles->getModelObjectId($pRole);

	$Permissions = new Silk_Permissions();
	$permissions = $Permissions->fetchByResource($resource);

	foreach ($permissions as $permission){
	    logdebug('Objects.clearPermissionsForRole: Clearing permissions on ' . $permission->resource . ' for role ' . $role_id);
	    Doctrine_Query::create()
		->delete('Silk_Dao_RolePermission rp')
		->where('rp.role_id = ?', $role_id)
		->andWhere('rp.permission_id = ?', $permission->permission_id)
		->execute();
	}
    }

    public function setPermissions($pObject, array $pRolePermissions, array $pUserPermissions){
	$object = $this->getModelObject($pObject);

	$resource = "object.{$object->object_id}";

	$Permissions = new Silk_Permissions();
	$Roles = new Silk_Roles();
	$Users = new Silk_Users();

	if (count($pRolePermissions) > 0){
	    $roles = $pRolePermissions['role'];
	    if (array_key_exists('privilege', $pRolePermissions)){
		$privileges = $pRolePermissions['privilege'];

		foreach ($roles as $i => $role_id){
		    $this->clearPermissionsForRole($object, $role_id);

		    $role_privileges = $privileges[$role_id];

		    foreach ($role_privileges as $privilege){
			$permission = $Permissions->fetchByResourceAndPrivilege($resource, $privilege);
			if ($permission){
			    logdebug("Objects.setPermission: Assigning permission {$permission->resource}.{$permission->privilege} to role {$role_id}");
			    $rp = new Silk_Dao_RolePermission();
			    $rp->role_id = $role_id;
			    $rp->permission_id = $permission->permission_id;
			    $rp->save();
			} else
			    logwarn("Attempting to assign an invalid permission {$resource}:{$privilege} to role {$role_id}");
		    }
		}
	    }
	}

	if (count($pUserPermissions) > 0){
	    $users = $pUserPermissions['user'];
	    if (array_key_exists('privilege', $pUserPermissions)){
		$privileges = $pUserPermissions['privilege'];

		foreach ($users as $i => $user_id){
		    if ($user_id != $object->user_id){
			$this->clearPermissionsForUser($object, $user_id);

			$user_privileges = $priviliges[$user_id];

			foreach ($user_privilges as $privilege){
			    $permission = $Permissions->fetchByResourceAndPrivilege($resource, $privilege);
			    if ($permission){
				$rp = new Silk_Dao_UserPermission();
				$rp->user_id = $user_id;
				$rp->permission_id = $permission->permission_id;
				$rp->save();
			    } else
				logwarn("Attempting to assign an invalid permission {$resource}:{$privilege} to user {$user_id}");
			}
		    }
		}
	    }
	}
    }

    public function delete($pObject){
	$object_id = $this->getModelObjectId($pObject);
	logdebug('Silk_Objects.delete: Called for object ' . $object_id);
	parent::delete($pObject);
    }

    public function postDelete($pObjectId){
	$resource = "object.{$pObjectId}";

	$Permissions = new Silk_Permissions();
	$permissions = $Permissions->fetchByResource($resource);

	foreach ($permissions as $permission)
	    $permission->delete();
    }

    public function postSave(array $pData){

	//Create Edit permission
	$permission_name = "Object {$pData['object_id']} Edit";
	$permission_resource = "object.{$pData['object_id']}";
	$permission_privilege = PERMISSION_EDIT;
	$permission_roles = array("Administrator");

	if (Silk::HasIdentity()){
	    $permission_roles[] = Silk::GetIdentity();
	}

	if (!Silk::PermissionExists(array('resource' => $permission_resource, 'privilege' => $permission_privilege))){
	    Silk::CreatePermission(
		$permission_name,
		$permission_resource,
		$permission_privilege,
		$permission_roles
	    );
	}

	//Create Delete Permission
	$permission_name = "Object {$pData['object_id']} Delete";
	$permission_resource = "object.{$pData['object_id']}";
	$permission_privilege = PERMISSION_DELETE;
	$permission_roles = array("Administrator");

	if (Silk::HasIdentity()){
	    $permission_roles[] = Silk::GetIdentity();
	}

	if (!Silk::PermissionExists(array('resource' => $permission_resource, 'privilege' => $permission_privilege))){
	    Silk::CreatePermission(
		$permission_name,
		$permission_resource,
		$permission_privilege,
		$permission_roles
	    );
	}

	//Create View Permission
	$permission_name = "Object {$pData['object_id']} View";
	$permission_resource = "object.{$pData['object_id']}";
	$permission_privilege = PERMISSION_VIEW;
	$permission_roles = array("Administrator", "Guest");

	if (Silk::HasIdentity()){
	    $permission_roles[] = Silk::GetIdentity();
	}

	if (!Silk::PermissionExists(array('resource' => $permission_resource, 'privilege' => $permission_privilege))){
	    Silk::CreatePermission(
		$permission_name,
		$permission_resource,
		$permission_privilege,
		$permission_roles
	    );
	}

	return $pData;

    }

    public function clearMetas($pObject){
	$object_id = $this->getModelObjectId($pObject);
	$Metas = new Silk_Metas();
	$metas = $Metas->fetchByObjectId($object_id);
	foreach ($metas as $meta)
	    $meta->delete();
    }

    public function updateMetas($pObject, $pMetas){
	$Metas = new Silk_Metas();
	return $Metas->getModelCollection($pMetas);

    }

    public function getSite($pObject)
    {
        $object = $this->getModelObject($pObject);

        $Sites = new Silk_Sites();

        return $Sites->fetch($object->site_id);
    }

    public function getUser($pObject)
    {
        $object = $this->getModelObject($pObject);

	if ($object->user_id){
	    $Users = new Silk_Users();

	    return $Users->fetch($object->user_id);
	} else
	    return null;

    }

    public function getType($pObject)
    {
        $object = $this->getModelObject($pObject);

        $Types = new Silk_Types();

        return $Types->fetch($object->type_id);
    }

    public function getModuleType($pObject){
	$type = $this->getType($pObject);

	if ($type->virtual)
	    $ModuleType = Silk::getVirtualTypeDefinition($type);
	else
	    $ModuleType = Silk::GetTypeDefinition($type->slug);

	return $ModuleType;
    }

    public function getParent($pObject)
    {
        $object = $this->getModelObject($pObject);

        $Objects = new Silk_Objects();

        return $Objects->fetch($object->parent_id);
    }

    public function getMetas($pObject)
    {
        $object_id = $this->getModelObjectId($pObject);

        $Metas = new Silk_Metas();

        return $Metas->getMetasForObject($object_id);
    }

    public function getTranslations($pObject)
    {
        $object_id = $this->getModelObjectId($pObject);

        $Translations = new Silk_Translations();

        return $Translations->getTranslationsForObject($object_id);
    }

    public function getChildren($pObject)
    {
        $object_id = $this->getModelObjectId($pObject);

        $Objects = new Silk_Objects();

        return $Objects->getObjectsForObject($object_id);
    }

    public function getTermTaxonomies($pObject)
    {
        $object_id = $this->getModelObjectId($pObject);

        $TermTaxonomys = new Silk_TermTaxonomys();

        return $TermTaxonomys->getTermTaxonomysForObject($object_id);
    }


}

 ?>